/**
 * 密码安全工具类
 * 包含RSA加密解密和bcrypt哈希功能
 */
const crypto = require("crypto");
const bcrypt = require("bcryptjs");
const fs = require("fs");
const path = require("path");

class PasswordSecurity {
  constructor() {
    this.keyPair = null;
    this.publicKey = null;
    this.privateKey = null;

    this.initializeKeys();
  }

  /**
   * 初始化RSA密钥对
   */
  initializeKeys() {
    const keyDir = path.join(__dirname, "../keys");
    const publicKeyPath = path.join(keyDir, "public_key.pem");
    const privateKeyPath = path.join(keyDir, "private_key.pem");

    try {
      // 尝试读取现有密钥
      if (fs.existsSync(publicKeyPath) && fs.existsSync(privateKeyPath)) {
        this.publicKey = fs.readFileSync(publicKeyPath, "utf8");
        this.privateKey = fs.readFileSync(privateKeyPath, "utf8");
        console.log("✅ 成功加载现有RSA密钥对");
      } else {
        // 生成新的密钥对
        this.generateKeyPair();
        this.saveKeys(keyDir, publicKeyPath, privateKeyPath);
      }
    } catch (error) {
      console.error("❌ RSA密钥初始化失败:", error);
      // 生成新密钥作为后备方案
      this.generateKeyPair();
    }
  }

  /**
   * 生成RSA密钥对
   */
  generateKeyPair() {
    console.log("🔑 正在生成新的RSA密钥对...");

    const keyPair = crypto.generateKeyPairSync("rsa", {
      modulusLength: 2048, // 2048位密钥
      publicKeyEncoding: {
        type: "spki",
        format: "pem",
      },
      privateKeyEncoding: {
        type: "pkcs8",
        format: "pem",
      },
    });

    this.keyPair = keyPair;
    this.publicKey = keyPair.publicKey;
    this.privateKey = keyPair.privateKey;

    console.log("✅ RSA密钥对生成成功");
  }

  /**
   * 保存密钥到文件
   */
  saveKeys(keyDir, publicKeyPath, privateKeyPath) {
    try {
      // 确保目录存在
      if (!fs.existsSync(keyDir)) {
        fs.mkdirSync(keyDir, { recursive: true });
      }

      // 保存公钥和私钥
      fs.writeFileSync(publicKeyPath, this.publicKey);
      fs.writeFileSync(privateKeyPath, this.privateKey);

      // 设置私钥文件权限（仅所有者可读）
      fs.chmodSync(privateKeyPath, 0o600);

      console.log("✅ RSA密钥已保存到文件系统");
    } catch (error) {
      console.warn("⚠️ 密钥保存失败，将使用内存中的密钥:", error.message);
    }
  }

  /**
   * 获取公钥（供前端使用）
   */
  getPublicKey() {
    return this.publicKey;
  }

  /**
   * 使用私钥解密密码
   * @param {string} encryptedPassword - 加密的密码
   * @returns {string} 解密后的明文密码
   */
  decryptPassword(encryptedPassword) {
    try {
      // Base64解码
      const encryptedBuffer = Buffer.from(encryptedPassword, "base64");

      // RSA私钥解密
      const decrypted = crypto.privateDecrypt(
        {
          key: this.privateKey,
          padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
          oaepHash: "sha256",
        },
        encryptedBuffer
      );

      return decrypted.toString("utf8");
    } catch (error) {
      console.error("❌ 密码解密失败:", error);
      throw new Error("密码解密失败，请检查加密格式");
    }
  }

  /**
   * 使用bcrypt对密码进行哈希
   * @param {string} plainPassword - 明文密码
   * @returns {Promise<string>} 哈希后的密码
   */
  async hashPassword(plainPassword) {
    try {
      const saltRounds = 12; // 推荐的盐值轮数
      const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
      return hashedPassword;
    } catch (error) {
      console.error("❌ 密码哈希失败:", error);
      throw new Error("密码哈希处理失败");
    }
  }

  /**
   * 验证密码
   * @param {string} plainPassword - 明文密码
   * @param {string} hashedPassword - 哈希密码
   * @returns {Promise<boolean>} 验证结果
   */
  async verifyPassword(plainPassword, hashedPassword) {
    try {
      return await bcrypt.compare(plainPassword, hashedPassword);
    } catch (error) {
      console.error("❌ 密码验证失败:", error);
      return false;
    }
  }

  /**
   * 完整的密码处理流程：解密 + 哈希
   * @param {string} encryptedPassword - RSA加密的密码
   * @returns {Promise<string>} bcrypt哈希后的密码
   */
  async processPasswordForStorage(encryptedPassword) {
    // 1. RSA解密
    const plainPassword = this.decryptPassword(encryptedPassword);

    // 2. bcrypt哈希
    const hashedPassword = await this.hashPassword(plainPassword);

    return hashedPassword;
  }

  /**
   * 完整的密码验证流程：解密 + 验证哈希
   * @param {string} encryptedPassword - RSA加密的密码
   * @param {string} storedHash - 存储的bcrypt哈希
   * @returns {Promise<boolean>} 验证结果
   */
  async verifyEncryptedPassword(encryptedPassword, storedHash) {
    try {
      // 1. RSA解密
      const plainPassword = this.decryptPassword(encryptedPassword);

      // 2. 验证bcrypt哈希
      return await this.verifyPassword(plainPassword, storedHash);
    } catch (error) {
      console.error("❌ 加密密码验证失败:", error);
      return false;
    }
  }

  /**
   * 生成强密码建议
   * @param {number} length - 密码长度
   * @returns {string} 强密码
   */
  generateStrongPassword(length = 12) {
    const charset =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
    let password = "";
    for (let i = 0; i < length; i++) {
      password += charset.charAt(Math.floor(Math.random() * charset.length));
    }
    return password;
  }

  /**
   * 密码强度检查
   * @param {string} password - 要检查的密码
   * @returns {object} 强度检查结果
   */
  checkPasswordStrength(password) {
    const checks = {
      length: password.length >= 8,
      uppercase: /[A-Z]/.test(password),
      lowercase: /[a-z]/.test(password),
      number: /\d/.test(password),
      special: /[!@#$%^&*(),.?":{}|<>]/.test(password),
    };

    const score = Object.values(checks).filter(Boolean).length;

    let strength = "weak";
    if (score >= 4) strength = "strong";
    else if (score >= 3) strength = "medium";

    return {
      score,
      strength,
      checks,
      suggestions: this.getPasswordSuggestions(checks),
    };
  }

  /**
   * 获取密码改进建议
   */
  getPasswordSuggestions(checks) {
    const suggestions = [];

    if (!checks.length) suggestions.push("密码长度至少8位");
    if (!checks.uppercase) suggestions.push("包含大写字母");
    if (!checks.lowercase) suggestions.push("包含小写字母");
    if (!checks.number) suggestions.push("包含数字");
    if (!checks.special) suggestions.push("包含特殊字符");

    return suggestions;
  }
}

// 创建单例实例
const passwordSecurity = new PasswordSecurity();

module.exports = passwordSecurity;
